/*!
 * @文件名 flash.c
 *
 * @功能描述
 *  1.FLASH模块初始化配置，实现FLASH读写函数
 *  2.vendor data 写入读取
 */

#include <stdio.h>
#include "flash.h"

flash_ssd_config_t flashSSDConfig;
status_t ret;
uint32_t failAddr;

ST_VENDOR_DATA gst_vendor_A_data_A;
ST_VENDOR_DATA gst_vendor_B_data_B;
ST_VENDOR_DATA gst_factory_data = {
		.crc32 = 0x0F0F0F0F,
		.mcu_upgrade_flag = 0x01,		///< MCU�������־
	    .screen_brightness= 0x02,		///< ��Ļ����
		.PN_VERSION0= 0x02,
		.PN_VERSION1= 0x02,
		.PN_VERSION2= 0x02,
		.PN_VERSION3= 0x02,
		.PN_VERSION4= 0x02,
		.PN_VERSION5= 0x02,
		.HARDWARE_VERSION0= 0x98,
		.HARDWARE_VERSION1= 0x02,
		.HARDWARE_VERSION2= 0x03,
		.HARDWARE_VERSION3= 0x04,
		.HARDWARE_VERSION4= 0x08,
		.HARDWARE_VERSION5= 0x09,
		.SOFTWARE_VERSION0= 0x02,
		.SOFTWARE_VERSION1= 0x02,
		.SOFTWARE_VERSION2= 0x02,
		.SOFTWARE_VERSION3= 0x02,
		.SOFTWARE_VERSION4= 0x02,
		.host_ack_upgrade= 0x00,//是否由host导致的升级复位标志

};

/*FUNCTION**********************************************************************
 *
 * Function Name : vendor_factory_set
 * Description   : 将vendor设置为工厂值
 *
 *END**************************************************************************/
void vendor_factory_set(void)
{
	gst_vendor_A_data_A = gst_factory_data;
	gst_vendor_B_data_B = gst_factory_data;
	gst_vendor_B_data_B.mcu_upgrade_flag = 0x00; //工厂设置将程序默认跳转为A区
    vendor_data_save();
}

/*FUNCTION**********************************************************************
 *
 * Function Name : flash_init
 * Description   : 初始化FLASH模块
 *
 *END**************************************************************************/
void flash_init(void)
{
    ret = FLASH_DRV_Init(&Flash_InitConfig0, &flashSSDConfig);
    DEV_ASSERT(STATUS_SUCCESS == ret);
    //vendor_factory_set();
    //FLASH_DRV_GetDFlashProtection(&flashSSDConfig,protectStatus1);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : flash_write
 * Description   : flash写函数，每次写入大小为128字节
 *
 *END**************************************************************************/
void flash_write(uint8_t * write_buffer,uint32_t address)
{
		ret = FLASH_DRV_EraseSector(&flashSSDConfig, address, FEATURE_FLS_DF_BLOCK_SECTOR_SIZE);
	    DEV_ASSERT(STATUS_SUCCESS == ret);

	    /* Disable Callback */
	    flashSSDConfig.CallBack = NULL_CALLBACK;

	    /* Verify the erase operation at margin level value of 1, user read */
	    ret = FLASH_DRV_VerifySection(&flashSSDConfig, address, 256 / FTFx_DPHRASE_SIZE, 1u);
	    DEV_ASSERT(STATUS_SUCCESS == ret);

	    /* Write some data to the erased PFlash sector */
	    ret = FLASH_DRV_Program(&flashSSDConfig, address, WRITE_BUFFER_SIZE, write_buffer);
	    DEV_ASSERT(STATUS_SUCCESS == ret);

	    /* Verify the program operation at margin level value of 1, user margin */
	    ret = FLASH_DRV_ProgramCheck(&flashSSDConfig, address, WRITE_BUFFER_SIZE, write_buffer, &failAddr, 1u);
	    DEV_ASSERT(STATUS_SUCCESS == ret);
}
/*FUNCTION**********************************************************************
 *
 * Function Name : flash_write_update
 * Description   : flash写升级数据函数，每次写入大小为2048字节
 *
 *END**************************************************************************/
void flash_write_update(uint8_t * write_buffer,uint32_t address)
{
		ret = FLASH_DRV_EraseSector(&flashSSDConfig, address, FEATURE_FLS_DF_BLOCK_SECTOR_SIZE);
	    DEV_ASSERT(STATUS_SUCCESS == ret);

	    /* Disable Callback */
	    flashSSDConfig.CallBack = NULL_CALLBACK;

	    /* Verify the erase operation at margin level value of 1, user read */
	    ret = FLASH_DRV_VerifySection(&flashSSDConfig, address, 256 / FTFx_DPHRASE_SIZE, 1u);
	    DEV_ASSERT(STATUS_SUCCESS == ret);

	    /* Write some data to the erased PFlash sector */
	    ret = FLASH_DRV_Program(&flashSSDConfig, address, WRITE_BUFFER_SIZE_UPDATA, write_buffer);
	    DEV_ASSERT(STATUS_SUCCESS == ret);

	    /* Verify the program operation at margin level value of 1, user margin */
	    ret = FLASH_DRV_ProgramCheck(&flashSSDConfig, address, WRITE_BUFFER_SIZE_UPDATA, write_buffer, &failAddr, 1u);
	    DEV_ASSERT(STATUS_SUCCESS == ret);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : flash_read_byte
 * Description   : 从flash的指定地址中读取指定长度的数据到buffer中
 *
 *END**************************************************************************/
uint16_t flash_read_byte(volatile uint8_t * flashPtr,uint8_t *buffer, uint32_t length)
{
	while (0UL != length) {
	   *(buffer++) = *(flashPtr++);
	   length--;
	           }
	return 0;

}

/*FUNCTION**********************************************************************
 *
 * Function Name : get_vendor_A_data
 * Description   : 从存放vendor A的地址中取出数据存到buffer中
 *
 *END**************************************************************************/
uint16_t get_vendor_A_data(uint8_t *buffer, uint32_t length)
{
    uint32_t u32Addr = 0x10000000;
	u32Addr += SECTOR_ADDR(EFM_SECTOR_VENDOR_A_DATA_NUM);
    __IO uint8_t *pu8Buf = (uint8_t *)u32Addr;
    while (0UL != length) {
       *(buffer++) = *(pu8Buf++);
       length--;
               }
	return 0;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : get_vendor_B_data
 * Description   : 从存放vendor B的地址中取出数据存到buffer中
 *
 *END**************************************************************************/
uint16_t get_vendor_B_data(uint8_t *buffer, uint32_t length)
{
    uint32_t u32Addr = 0x10000000;
	u32Addr += SECTOR_ADDR(EFM_SECTOR_VENDOR_B_DATA_NUM);
    __IO uint8_t *pu8Buf = (uint8_t *)u32Addr;
    while (0UL != length) {
       *(buffer++) = *(pu8Buf++);
       length--;
               }
	return 0;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Utils_CRC32
 * Description   : 计算CRC值
 *
 *END**************************************************************************/
uint32_t Utils_CRC32(const uint8_t *data, size_t len)
{
    uint32_t crc = 0xFFFFFFFF;
    uint8_t byte = 0;
    while (len--)
    {
        byte = *data++;
        crc ^= byte;
        for (int j = 0; j < 8; j++)
        {
            uint32_t mask = -(crc & 1);
            crc = (crc >> 1) ^ (0xEDB88320 & mask);
        }
    }
    return ~crc;
}
/*FUNCTION**********************************************************************
 *
 * Function Name : vendor_verify_data
 * Description   : 校验CRC是否正确来判断vendor有效性
 *
 *END**************************************************************************/
static uint8_t vendor_verify_data(ST_VENDOR_DATA *verify_data, uint16_t dataLen)
{
    uint32_t read_crc32 = verify_data->crc32;
    uint32_t verify_crc32 = 0;

    verify_data->crc32 = VENDOR_CRC32_DEFAULT_VALUE;
    verify_crc32 = Utils_CRC32((const uint8_t *)verify_data, dataLen);
    verify_data->crc32 = read_crc32;
    if (verify_crc32 != read_crc32)
    {
        return 1;
    }
    return 0;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : vendor_data_A_load
 * Description   : 加载vendor data A
 *
 *END**************************************************************************/
bool vendor_data_A_load(void)
{
	bool read_result = false;
	get_vendor_A_data((uint8_t *)&gst_vendor_A_data_A, sizeof(gst_vendor_A_data_A));
    if (vendor_verify_data(&gst_vendor_A_data_A, sizeof(ST_VENDOR_DATA)) == 0)
    {
        read_result = true;
    }

   return read_result;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : vendor_data_B_load
 * Description   : 加载vendor data B
 *
 *END**************************************************************************/
bool vendor_data_B_load(void)
{
	bool read_result = false;
    get_vendor_B_data((uint8_t *)&gst_vendor_B_data_B, sizeof(gst_vendor_B_data_B));
    if (vendor_verify_data(&gst_vendor_B_data_B, sizeof(ST_VENDOR_DATA)) == 0)
    {
        read_result = true;
    }
   return read_result;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : vendor_data_save
 * Description   : 将vendor结构体存储到DFLASH中
 *
 *END**************************************************************************/
void vendor_data_save(void)
{
    /* CRC32 calc. */
    gst_vendor_A_data_A.crc32 = VENDOR_CRC32_DEFAULT_VALUE;
    gst_vendor_A_data_A.crc32 = Utils_CRC32((const uint8_t *)&gst_vendor_A_data_A, sizeof(gst_vendor_A_data_A));
    flash_write((uint8_t *)&gst_vendor_A_data_A,0x10007C00);
    gst_vendor_B_data_B.crc32 = VENDOR_CRC32_DEFAULT_VALUE;
    gst_vendor_B_data_B.crc32 = Utils_CRC32((const uint8_t *)&gst_vendor_B_data_B, sizeof(gst_vendor_B_data_B));
    flash_write((uint8_t *)&gst_vendor_B_data_B,0x10007000);
}
